//// [variadicTuples2.ts]
// Declarations

type V00 = [number, ...string[]];
type V01 = [...string[], number];
type V03 = [number, ...string[], number];

type V10 = [number, ...string[], ...boolean[]];  // Error
type V11 = [number, ...string[], boolean?];  // Error
type V12 = [number, string?, boolean];  // Error

// Normalization

type Tup3<T extends unknown[], U extends unknown[], V extends unknown[]> = [...T, ...U, ...V];

type V20 = Tup3<[number], string[], [number]>;  // [number, ...string[], number]
type V21 = Tup3<[number], [string?], [boolean]>;  // [number, string | undefined, boolean]
type V22 = Tup3<[number], string[], boolean[]>;  // [number, (string | boolean)[]]
type V23 = Tup3<[number], string[], [boolean?]>;  // [number, (string | boolean | undefined)[]]
type V24 = Tup3<[number], [boolean?], string[]>;  // [number, boolean?, ...string[]]
type V25 = Tup3<string[], number[], boolean[]>;  // (string | number | boolean)[]
type V26 = Tup3<string[], number[], [boolean]>;  // [...(string | number)[], boolean]
type V27 = Tup3<[number?], [string], [boolean?]>;  // [number | undefined, string, boolean?]

type V30<A extends unknown[]> = Tup3<A, string[], number[]>;  // [...A, ...(string | number)[]]
type V31<A extends unknown[]> = Tup3<string[], A, number[]>;  // (string | number | A[number])[]
type V32<A extends unknown[]> = Tup3<string[], number[], A>;  // [...(string | number)[], ...A]

type V40<A extends unknown[]> = Tup3<A, [string?], number[]>;  // [...A, string?, ...number[]]
type V41<A extends unknown[]> = Tup3<[string?], A, number[]>;  // [string?, ...A, ...number[]]
type V42<A extends unknown[]> = Tup3<[string?], number[], A>;  // [string?, ...number[], ...A]

type V50<A extends unknown[]> = Tup3<A, string[], [number?]>;  // [...A, ...(string | number | undefined)[]]
type V51<A extends unknown[]> = Tup3<string[], A, [number?]>;  // (string | number | A[number] | undefined)[]
type V52<A extends unknown[]> = Tup3<string[], [number?], A>;  // [...(string | number | undefined)[], ...A]

// Assignability

declare let tt1: [...string[], number];
tt1 = [5];
tt1 = ['abc', 5];
tt1 = ['abc', 'def', 5];
tt1 = ['abc', 'def', 5, 6];  // Error

declare function ft1(...args: [...strs: string[], num: number]): void;
ft1(5);
ft1('abc', 5);
ft1('abc', 'def', 5);
ft1('abc', 'def', 5, 6);  // Error

declare let tt2: [number, ...string[], number];
tt2 = [0];  // Error
tt2 = [0, 1];
tt2 = [0, 1, 2];  // Error
tt2 = [0, 'abc', 1];
tt2 = [0, 'abc', 'def', 1];
tt2 = [0, 'abc', 1, 'def'];  // Error
tt2 = [true, 'abc', 'def', 1];  // Error
tt2 = [0, 'abc', 'def', true];  // Error

declare function ft2(n1: number, ...rest: [...strs: string[], n2: number]): void;
ft2(0);  // Error
ft2(0, 1);
ft2(0, 1, 2);  // Error
ft2(0, 'abc', 1);
ft2(0, 'abc', 'def', 1);
ft2(0, 'abc', 1, 'def');  // Error
ft2(true, 'abc', 'def', 1);  // Error
ft2(0, 'abc', 'def', true);  // Error

function ft3<T extends unknown[]>(x: [number, ...T], y: [number, number], z: [number, ...number[]]) {
    x = y;  // Error
    x = z;  // Error
    y = x;  // Error
    z = x;  // Error
}

// Inference

function pipe<T extends readonly unknown[]>(...args: [...T, (...values: T) => void]) {
    const callback = args[args.length - 1] as (...values: T) => void;
    const values = args.slice(0, -1) as unknown as T;
    callback(...values);
}

pipe("foo", 123, true, (a, b, c) => {
    a;  // string
    b;  // number
    c;  // boolean
})

pipe("foo", 123, true, (...x) => {
    x;  // [string, number, boolean]
});

declare const sa: string[];

pipe(...sa, (...x) => {
    x;  // string[]
});

pipe(1, ...sa, 2, (...x) => {
    x;  // [number, ...string[], number]
    let qq = x[x.length - 1];
    let ww = x[0]
});

pipe<number[]>(1, 2, 3, 4);  // Error
pipe(...sa);  // Error

declare function fn1<T, U>(t: [...unknown[], T, U]): [T, U];
fn1([]);  // Error
fn1([1]);  // Error
fn1([1, 'abc']);  // [number, string]
fn1([1, 'abc', true]);  // [string, boolean]

declare function fn2<T, U>(t: [T, ...unknown[], U]): [T, U];
fn2([]);  // Error
fn2([1]);  // Error
fn2([1, 'abc']);  // [number, string]
fn2([1, 'abc', true]);  // [number, boolean]

// Repro from #39595

declare function foo<S extends readonly [string, ...string[]]>(...stringsAndNumber: readonly [...S, number]): [...S, number];
    
const a1 = foo('blah1', 1);
const b1 = foo('blah1', 'blah2', 1);
const c1 = foo(1);  // Error
const d1 = foo(1, 2);  // Error
const e1 = foo('blah1', 'blah2', 1, 2, 3);  // Error


//// [variadicTuples2.js]
"use strict";
// Declarations
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};
tt1 = [5];
tt1 = ['abc', 5];
tt1 = ['abc', 'def', 5];
tt1 = ['abc', 'def', 5, 6]; // Error
ft1(5);
ft1('abc', 5);
ft1('abc', 'def', 5);
ft1('abc', 'def', 5, 6); // Error
tt2 = [0]; // Error
tt2 = [0, 1];
tt2 = [0, 1, 2]; // Error
tt2 = [0, 'abc', 1];
tt2 = [0, 'abc', 'def', 1];
tt2 = [0, 'abc', 1, 'def']; // Error
tt2 = [true, 'abc', 'def', 1]; // Error
tt2 = [0, 'abc', 'def', true]; // Error
ft2(0); // Error
ft2(0, 1);
ft2(0, 1, 2); // Error
ft2(0, 'abc', 1);
ft2(0, 'abc', 'def', 1);
ft2(0, 'abc', 1, 'def'); // Error
ft2(true, 'abc', 'def', 1); // Error
ft2(0, 'abc', 'def', true); // Error
function ft3(x, y, z) {
    x = y; // Error
    x = z; // Error
    y = x; // Error
    z = x; // Error
}
// Inference
function pipe() {
    var args = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        args[_i] = arguments[_i];
    }
    var callback = args[args.length - 1];
    var values = args.slice(0, -1);
    callback.apply(void 0, values);
}
pipe("foo", 123, true, function (a, b, c) {
    a; // string
    b; // number
    c; // boolean
});
pipe("foo", 123, true, function () {
    var x = [];
    for (var _i = 0; _i < arguments.length; _i++) {
        x[_i] = arguments[_i];
    }
    x; // [string, number, boolean]
});
pipe.apply(void 0, __spreadArray(__spreadArray([], sa, false), [function () {
        var x = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            x[_i] = arguments[_i];
        }
        x; // string[]
    }], false));
pipe.apply(void 0, __spreadArray(__spreadArray([1], sa, false), [2, function () {
        var x = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            x[_i] = arguments[_i];
        }
        x; // [number, ...string[], number]
        var qq = x[x.length - 1];
        var ww = x[0];
    }], false));
pipe(1, 2, 3, 4); // Error
pipe.apply(void 0, sa); // Error
fn1([]); // Error
fn1([1]); // Error
fn1([1, 'abc']); // [number, string]
fn1([1, 'abc', true]); // [string, boolean]
fn2([]); // Error
fn2([1]); // Error
fn2([1, 'abc']); // [number, string]
fn2([1, 'abc', true]); // [number, boolean]
var a1 = foo('blah1', 1);
var b1 = foo('blah1', 'blah2', 1);
var c1 = foo(1); // Error
var d1 = foo(1, 2); // Error
var e1 = foo('blah1', 'blah2', 1, 2, 3); // Error


//// [variadicTuples2.d.ts]
type V00 = [number, ...string[]];
type V01 = [...string[], number];
type V03 = [number, ...string[], number];
type V10 = [number, ...string[], ...boolean[]];
type V11 = [number, ...string[], boolean?];
type V12 = [number, string?, boolean];
type Tup3<T extends unknown[], U extends unknown[], V extends unknown[]> = [...T, ...U, ...V];
type V20 = Tup3<[number], string[], [number]>;
type V21 = Tup3<[number], [string?], [boolean]>;
type V22 = Tup3<[number], string[], boolean[]>;
type V23 = Tup3<[number], string[], [boolean?]>;
type V24 = Tup3<[number], [boolean?], string[]>;
type V25 = Tup3<string[], number[], boolean[]>;
type V26 = Tup3<string[], number[], [boolean]>;
type V27 = Tup3<[number?], [string], [boolean?]>;
type V30<A extends unknown[]> = Tup3<A, string[], number[]>;
type V31<A extends unknown[]> = Tup3<string[], A, number[]>;
type V32<A extends unknown[]> = Tup3<string[], number[], A>;
type V40<A extends unknown[]> = Tup3<A, [string?], number[]>;
type V41<A extends unknown[]> = Tup3<[string?], A, number[]>;
type V42<A extends unknown[]> = Tup3<[string?], number[], A>;
type V50<A extends unknown[]> = Tup3<A, string[], [number?]>;
type V51<A extends unknown[]> = Tup3<string[], A, [number?]>;
type V52<A extends unknown[]> = Tup3<string[], [number?], A>;
declare let tt1: [...string[], number];
declare function ft1(...args: [...strs: string[], num: number]): void;
declare let tt2: [number, ...string[], number];
declare function ft2(n1: number, ...rest: [...strs: string[], n2: number]): void;
declare function ft3<T extends unknown[]>(x: [number, ...T], y: [number, number], z: [number, ...number[]]): void;
declare function pipe<T extends readonly unknown[]>(...args: [...T, (...values: T) => void]): void;
declare const sa: string[];
declare function fn1<T, U>(t: [...unknown[], T, U]): [T, U];
declare function fn2<T, U>(t: [T, ...unknown[], U]): [T, U];
declare function foo<S extends readonly [string, ...string[]]>(...stringsAndNumber: readonly [...S, number]): [...S, number];
declare const a1: ["blah1", number];
declare const b1: ["blah1", "blah2", number];
declare const c1: [string, ...string[], number];
declare const d1: [string, ...string[], number];
declare const e1: [string, ...string[], number];
